//Linux Headers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>
#include <errno.h>

//WiringPI Headers
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <wiringSerial.h>


#define LED 7//8
#define sSDA 15
#define sSCL 16

sem_t Semaphore;

int32_t Cnt_sSDA=0;
int32_t Cnt_sSCL=0;
unsigned int ArduinoData=0;

void digitalWriteToggle(unsigned char PinNo)
{
	if(digitalRead(PinNo)){
		digitalWrite (PinNo, 0) ;	
	}
	else{
		digitalWrite (PinNo, 1) ;	
	}
}

int PutInt_Exosite(char *pCIK, char *pDataAlias, int Data)
{
	int RetVal=0;
	char Command[300];
	FILE *fp = NULL;

	sprintf(Command, "curl -s http://m2.exosite.com/onep:v1/stack/alias \
					-H 'X-Exosite-CIK: %s' \
					-H 'Accept: application/x-www-form-urlencoded; charset=utf-8' \
					-d '%s=%d'", pCIK, pDataAlias, Data);
	//printf("\n%s\n", Command);				
	fp=popen(Command, "r");
	if(fp){
		fgetc(fp);
		if(feof(fp)){
			//printf("Ok\n");
			RetVal=0;
		}
		else{
			//printf("Fail\n");
			RetVal=-2;
		}
	}	
	else{
		//printf("error [%d:%s]\n", errno, strerror(errno));
		RetVal=-1;
	}	
	pclose(fp);
	return RetVal;
}

int GetInt_Exosite(char *pCIK, char *pDataAlias, int *pData)
{
	int RetVal=0;
	char Command[300];
	char Result[100];
	FILE *fp = NULL;
	char *pChar;
	
	sprintf(Command, "curl -s http://m2.exosite.com/onep:v1/stack/alias?%s \
					-H 'X-Exosite-CIK: %s' \
					-H 'Accept: application/x-www-form-urlencoded; charset=utf-8'", pDataAlias, pCIK);
	fp=popen(Command, "r");
	if(fp){
		fgets(Result, sizeof(Result), fp);
		pChar=strstr(Result, pDataAlias);
		if(pChar != NULL){
			pChar=pChar+strlen(pDataAlias)+1; // '+1' is '='
			*pData=atoi(pChar);
			RetVal=0;
		}
		else{
			//printf("Error\n");
			RetVal=-2;
		}
	}	
	else{
		//printf("error [%d:%s]\n", errno, strerror(errno));
		RetVal=-1;
	}
	pclose(fp);
	return RetVal;
}



void* Thread1(void *data)
{
//	(void)piHiPri (10) ;
	for (;;)
	{
		//printf("1"); fflush(stdout);
		digitalWriteToggle(LED);
		usleep(500*1000); //500ms 동안 대기
	}
}


int PutData=0;

void* Thread2(void *data)
{
	int GetData;
	while(1){
		printf("G");fflush(stdout);

		if(GetInt_Exosite("bb26ddb330be61752bce11cfb33f4ce204817a3d","windspeed", &GetData)){
			printf("Error: Get\n");fflush(stdout);
		}
		else{
			printf("%d--", GetData);fflush(stdout);
		}
		
		PutData=GetData+1;
		sem_post(&Semaphore);
		sleep(5);
	}
}


void* Thread3(void *data)
{
	while(1){
		sem_wait(&Semaphore);

		printf("P");fflush(stdout);
		if(PutInt_Exosite("bb26ddb330be61752bce11cfb33f4ce204817a3d", "windspeed", PutData)){
			printf("Error: Put\n");fflush(stdout);
		}
		else{
			//Nothing
		}
		
		printf("%d\n", PutData);fflush(stdout);
	}
}


#define I2C_ID_PCF8574A 0x38
void* Thread4(void *data)
{
	int fd;
	fd=wiringPiI2CSetup(I2C_ID_PCF8574A);
	
	for (;;)
	{
		wiringPiI2CWrite (fd, 0x55);
		//printf("Cnt_sSDA=%d, Cnt_sSCL=%d\n", Cnt_sSDA, Cnt_sSCL); //fflush(stdout);
		usleep(500*1000);
		wiringPiI2CWrite (fd, 0xaa);
		//printf("Cnt_sSDA=%d, Cnt_sSCL=%d\n", Cnt_sSDA, Cnt_sSCL); //fflush(stdout);
		usleep(500*1000);
	}
}

void* Thread5(void *data)
{
	int fd ;

	char RxBuf, IdxRxBuf;
	unsigned int Rxd=0;
  	if ((fd = serialOpen ("/dev/ttyACM0", 115200)) >= 0){
		for (;;){
			while(serialDataAvail (fd)){
				RxBuf=(char)serialGetchar(fd);
				if(RxBuf=='~'){
					IdxRxBuf=0;
					Rxd=0;
				}
				else{
					Rxd=Rxd | (((RxBuf<='9') ? (RxBuf-'0') : (RxBuf-'A'+10)) * (0x1000>>(IdxRxBuf*4)));
					IdxRxBuf++;
				}

				if(IdxRxBuf >= 4){
					//printf("%d\n", Rxd);fflush(stdout);
					ArduinoData=Rxd;
				}
				//printf("%c", RxBuf);fflush(stdout);
			}
			usleep(1);
		}
  	}
	else{
		fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
	}
	serialClose(fd);
}





void ISR_sSDA(void)
{
	Cnt_sSDA++;
//	printf("D");fflush(stdout);
/*
	if(digitalRead(InSig)){
//		wiringPiISR (InSig, INT_EDGE_FALLING, &ISR_GPIO16);
		pinMode (TestSig, OUTPUT) ;
	}
	else{
//		wiringPiISR (InSig, INT_EDGE_RISING, &ISR_GPIO16);
		pinMode (TestSig, INPUT) ;
	}
*/
}


void ISR_sSCL(void)
{
	Cnt_sSCL++;
//	printf("C");fflush(stdout);
/*
	if(digitalRead(InSig)){
//		wiringPiISR (InSig, INT_EDGE_FALLING, &ISR_GPIO16);
		pinMode (TestSig, OUTPUT) ;
	}
	else{
//		wiringPiISR (InSig, INT_EDGE_RISING, &ISR_GPIO16);
		pinMode (TestSig, INPUT) ;
	}
*/
}


void PlayMP3(void)
{
	system ("mpg321 -g 100 /root/MkWorks/DongDong3/Test.mp3"); 
	//system ("/root/MkWorks/DongDong3/test.sh");
}

void setup (void)
{
	pthread_t p_thread[4];
	
	wiringPiSetup();
	pinMode (LED, OUTPUT) ;
	pinMode (sSDA, INPUT) ;
	pinMode (sSCL, INPUT) ;
	digitalWrite (LED, 0) ;	

	wiringPiISR (sSDA, INT_EDGE_BOTH, &ISR_sSDA);
	wiringPiISR (sSCL, INT_EDGE_BOTH, &ISR_sSCL);
	

//	system ("gpio load i2c 100"); //Load I2C Device Driver Module as 100Kbps

	sem_init(&Semaphore, 0, 0);
	pthread_create(&p_thread[0], NULL, Thread1, NULL);
	pthread_create(&p_thread[1], NULL, Thread2, NULL);
	pthread_create(&p_thread[2], NULL, Thread3, NULL);
	pthread_create(&p_thread[3], NULL, Thread4, NULL);
	pthread_create(&p_thread[4], NULL, Thread5, NULL);
	
	pthread_detach(p_thread[0]);
	pthread_detach(p_thread[1]); 
	pthread_detach(p_thread[2]);
	pthread_detach(p_thread[3]);
	pthread_detach(p_thread[4]);
}

int main (void)
{
	printf("\n Start...\n"); fflush(stdout);

	(void)piHiPri (10);

	setup();
/*
	if(fork() == 0)
	{
		PlayMP3();
		return -1;	
	}
*/	
	for (;;)
	{
//		printf("Cnt_sSDA=%d, Cnt_sSCL=%d\n", Cnt_sSDA, Cnt_sSCL); //fflush(stdout);
		sleep(1);
		//delay (1000);
	}
	
	pause();
	printf("\n End...\n"); fflush(stdout);
	return 0 ;
}
